﻿
// CMainDlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "CClient.h"
#include "CMainDlg.h"
#include "afxdialogex.h"
#include "CWorkerDlg.h"
#include "CCreateExDlg.h"
#include "CSendOrPost.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CMainDlg 对话框
/*
资源中默认未设置ID的控件，看不到控件的变量类，IDC_STATIC是公共ID

运算符类型转换
CWnd w1;
HWND h = w1; 
	operator HWND() const
	{ return this == NULL ? NULL : m_hWnd; }

CWnd::Create、CreateEx
	拖入对话框的资源控件，通过此函数创建

*/

CMainDlg::CMainDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_MAIN, pParent)
{
	// m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	// theApp.m_hInstance 或 AfxGetInstanceHandle() 自己传入窗口句柄加载图标
	m_hIcon = LoadIcon(AfxGetInstanceHandle(), (LPCWSTR) IDR_MAINFRAME);
}

BEGIN_MESSAGE_MAP(CMainDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_MAIN_EXIT, &CMainDlg::OnClickedExit)
	ON_BN_CLICKED(IDC_MAIN_WORK, &CMainDlg::OnClickedWork)
	ON_BN_CLICKED(IDC_REMOVE_TEXT, &CMainDlg::OnClickedRemoveText)
	ON_BN_CLICKED(IDC_REMOVE_XOR, &CMainDlg::OnClickedRemoveXor)
	ON_BN_CLICKED(IDC_MAIN_NODE, &CMainDlg::OnClickedMainNode)
	ON_BN_CLICKED(IDC_MAIN_CREATE, &CMainDlg::OnClickedMainCreate)
	ON_BN_CLICKED(IDC_REMOVE_XOR2, &CMainDlg::OnClickedRemoveXor2)
	ON_BN_CLICKED(IDC_MAIN_WINDOW_POINT, &CMainDlg::OnClickedMainWindowPoint)
	ON_BN_CLICKED(IDC_MAIN_MSG, &CMainDlg::OnClickedMainMsg)
END_MESSAGE_MAP()


// CMainDlg 消息处理程序

BOOL CMainDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	// 隐藏任务栏显示，但加了之后标题栏关闭x显示不行，需要重新自定义
	// ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW);

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	return FALSE;//  FALSE 防止Windows自动设置焦点到第一个可聚焦控件
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void CMainDlg::OnPaint()
{
	CPaintDC dc(this); // 用于绘制的设备上下文
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMainDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}



void CMainDlg::OnOK()
{
	// 默认实现，回车会调用到，如果有按钮接管了IDOK，当前也不会回调

	CDialogEx::OnOK();
}


void CMainDlg::OnCancel()
{
	// 默认实现，ESC会调用到，如果有按钮接管了IDCANCEL，当前也不会回调

	CDialogEx::OnCancel();
}


void CMainDlg::OnClickedExit()
{
	EndDialog(IDCANCEL);
}


void CMainDlg::OnClickedWork()
{
	if (theApp.sockeInit()) {
		CWorkerDlg dlg;
		dlg.DoModal();
	}
	else {
		AfxMessageBox(_T("服务器连接失败"));
	}
}


void CMainDlg::OnClickedRemoveText()
{
	CString path, text;
	GetDlgItemText(IDC_EDIT_PATH, path);
	GetDlgItemText(IDC_EDIT_TEXT, text);
	if (path.IsEmpty() || text.IsEmpty()) {
		AfxMessageBox(_T("路径或文字为NULL"));
		return;
	}
	FileRename(path, text);
}

void CMainDlg::FileRename(CString path, CString text)
{
	CFileFind finder;
	BOOL bWorking = finder.FindFile(path + _T("\\*.*")); // 列出所有文件
	while (bWorking) {
		bWorking = finder.FindNextFile();
		if (finder.IsDots()) {
			continue;
		}
		if (finder.IsDirectory() && !finder.IsDots()) {
			// 如果是文件夹且不是 "." 或 ".."，可以选择递归调用
			FileRename(finder.GetFilePath(), text);
		}
		else {
			CString oldFilePath = finder.GetFilePath();
			CString oldFileName = finder.GetFileName();
			oldFileName.Replace(text, _T(""));
			CString newFilePath = path + _T("\\") + oldFileName;
			// 重命名文件 CFile::Rename函数没有返回值
			BOOL result = MoveFileEx(oldFilePath, newFilePath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH);
			if (result) {
				TRACE(newFilePath + _T("\n"));
			}
			else {
				TRACE(newFilePath + _T(" error \n"));
			}
		}
	}
	finder.Close();
}

void CMainDlg::FileRenameEncryptionForXOR(CString path)
{
	CFileFind finder;
	BOOL bWorking = finder.FindFile(path + _T("\\*.*")); // 列出所有文件
	while (bWorking) {
		bWorking = finder.FindNextFile();
		if (finder.IsDots()) {
			continue;
		}
		if (finder.IsDirectory() && !finder.IsDots()) {
			// 如果是文件夹且不是 "." 或 ".."，可以选择递归调用
			FileRenameEncryptionForXOR(finder.GetFilePath());
		}
		else {
			CString oldFilePath = finder.GetFilePath();
			CString oldFileName = finder.GetFileName();
			CString newFileName;
			if (oldFileName.ReverseFind('.') == -1) {
				// 没有找到后缀，解密
				//newFileName = HexStringToString(oldFileName);
				//newFileName = XOREncryptDecrypt(newFileName, _T("12345"));
			}
			else {
				// 找到后缀，加密
				newFileName = XOREncryptDecrypt(oldFileName, _T("12345"));
				newFileName = StringToHexString(newFileName);
				CString newFilePath = path + _T("\\") + newFileName;
				// 重命名文件 CFile::Rename函数没有返回值
				BOOL result = MoveFileEx(oldFilePath, newFilePath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH);
				if (result) {
					TRACE(newFilePath + _T("\n"));
				}
				else {
					AfxMessageBox(newFilePath + _T(" is error!"));
					TRACE(newFilePath + _T(" error \n"));
				}
			}
		}
	}
	finder.Close();
}

void CMainDlg::FileRenameDecryptionForXOR(CString path)
{
	CFileFind finder;
	BOOL bWorking = finder.FindFile(path + _T("\\*.*")); // 列出所有文件
	while (bWorking) {
		bWorking = finder.FindNextFile();
		if (finder.IsDots()) {
			continue;
		}
		if (finder.IsDirectory() && !finder.IsDots()) {
			// 如果是文件夹且不是 "." 或 ".."，可以选择递归调用
			FileRenameDecryptionForXOR(finder.GetFilePath());
		}
		else {
			CString oldFilePath = finder.GetFilePath();
			CString oldFileName = finder.GetFileName();
			CString newFileName;
			if (oldFileName.ReverseFind('.') == -1) {
				// 没有找到后缀，解密
				newFileName = HexStringToString(oldFileName);
				newFileName = XOREncryptDecrypt(newFileName, _T("12345"));
				CString newFilePath = path + _T("\\") + newFileName;
				// 重命名文件 CFile::Rename函数没有返回值
				BOOL result = MoveFileEx(oldFilePath, newFilePath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH);
				if (result) {
					TRACE(newFilePath + _T("\n"));
				}
				else {
					AfxMessageBox(newFilePath + _T(" is error!"));
					TRACE(newFilePath + _T(" error \n"));
				}
			}
			else {
				// 找到后缀，加密
				//newFileName = XOREncryptDecrypt(oldFileName, _T("12345"));
				//newFileName = StringToHexString(newFileName);
			}
		}
	}
	finder.Close();
}

CString CMainDlg::XOREncryptDecrypt(CString input, CString key)
{
	CString output;
	// 遍历输入字符串
	for (int i = 0; i < input.GetLength(); i++) {
		// 使用异或运算进行加密/解密
		output += static_cast<wchar_t>(input[i] ^ key[i % key.GetLength()]);
	}
	return output;
}

CString CMainDlg::StringToHexString(const CString& strInput)
{
	CString strHex;
	for (int i = 0; i < strInput.GetLength(); ++i)
	{
		wchar_t ch = strInput[i];
		char szTemp[5] = { 0 };
		_snprintf_s(szTemp, sizeof(szTemp), "%04X", ch);
		strHex += szTemp;
	}
	return strHex;
}

CString CMainDlg::HexStringToString(const CString& strHex)
{
	int nLen = strHex.GetLength();
	if (nLen % 4 != 0)
		return _T("");

	CString strOutput;
	for (int i = 0; i < nLen; i += 4) {
		unsigned short usCharValue;
		_stscanf_s(strHex.Mid(i).GetString(), _T("%4hx"), &usCharValue);
		strOutput += static_cast<wchar_t>(usCharValue);
	}

	return strOutput;
}

void CMainDlg::OnClickedRemoveXor()
{
	CString path, text;
	GetDlgItemText(IDC_EDIT_PATH, path);
	if (path.IsEmpty()) {
		AfxMessageBox(_T("路径为NULL"));
		return;
	}
	FileRenameEncryptionForXOR(path);
}


void CMainDlg::OnClickedMainNode()
{
	// 模态对话框
	//EndDialog(IDCANCEL);
	//CNodeDlg dlg;
	//dlg.DoModal();
	
	// 非模态对话框 或者写成单例
	//CNodeDlg* dlg = new CNodeDlg;
	//// dlg->Create(IDD_NODE, this);// 创建时换成桌面可以成为平级
	//dlg->Create(IDD_NODE, GetDesktopWindow());
	//dlg->ShowWindow(SW_SHOW);

	if (IsWindow(m_nodeDlg.m_hWnd)) {
		// 判断窗口是否创建
	}

	if (!m_nodeDlg) {
		m_nodeDlg.Create(IDD_NODE, GetDesktopWindow());
	}
	m_nodeDlg.ShowWindow(SW_SHOW);
}


void CMainDlg::OnClickedMainCreate()
{
	CCreateExDlg dlg;
	dlg.DoModal();
}


void CMainDlg::OnClickedRemoveXor2()
{
	CString path, text;
	GetDlgItemText(IDC_EDIT_PATH, path);
	if (path.IsEmpty()) {
		AfxMessageBox(_T("路径为NULL"));
		return;
	}
	FileRenameDecryptionForXOR(path);
}


void CMainDlg::OnClickedMainWindowPoint()
{
	// 下面是：当前dialog放于屏幕左上角的坐标点
	// 获取屏幕点所在的窗口的顶层控件
	CWnd* p = WindowFromPoint(POINT{ 352, 159 });
	// 获取class name
	TCHAR s[256];
	GetClassName(p->GetSafeHwnd(), s, _countof(s));
	// 获取窗口标题
	CString str;
	p->GetWindowText(str);
	CString cn = s;
	TRACE(cn + _T("\n"));
	TRACE(str + _T("\n"));

	// 子窗口，父View的相对坐标
	p = p->ChildWindowFromPoint({ 50, 50 });
	// 获取class name
	GetClassName(p->GetSafeHwnd(), s, _countof(s));
	// 获取窗口标题
	p->GetWindowText(str);
	cn = s;
	TRACE(cn + _T("\n"));
	TRACE(str + _T("\n"));

	// 获取当前View的顶层View，找不到就NULL
	auto tP = p->GetTopWindow();
	if (tP) {
		// 获取class name
		GetClassName(tP->GetSafeHwnd(), s, _countof(s));
		// 获取窗口标题
		tP->GetWindowText(str);
		cn = s;
		TRACE(cn + _T("\n"));
		TRACE(str + _T("\n"));
	}
	
	// 获取父窗口
	auto pP = p->GetParent();
	auto pP2 = p->GetOwner();// 一层父View时与Parent相同，其他未测试
	// 获取class name
	GetClassName(pP->GetSafeHwnd(), s, _countof(s));
	// 获取窗口标题
	pP->GetWindowText(str);
	cn = s;
	TRACE(cn + _T("\n"));
	TRACE(str + _T("\n"));

	// GW_CHILD子 GW_OWNER父 GW_HWNDFIRST GW_HWNDLAST 同级最前和最后
	// GW_HWNDNEXT GW_HWNDPREV 同级前和后
	p->GetWindow(GW_OWNER);

	// 前面是类名后面是title名，任选其一，可以通过Spy获取
	p = FindWindow(_T("#32770"), NULL);
	p->GetWindowText(str);
	TRACE(str + _T("\n"));

	// 获取桌面window
	auto p5 = GetDesktopWindow();
	auto p55 = p5->GetWindow(GW_CHILD);
	while (p55) {
		GetClassName(p55->GetSafeHwnd(), s, _countof(s));
		p55->GetWindowText(str);
		TRACE(_T("%s ---> %s \n"),str, s);
		p55 = p55->GetWindow(GW_HWNDNEXT);
	}
}


void CMainDlg::OnClickedMainMsg()
{
	CSendOrPost dlg;
	dlg.DoModal();
}
